package devent.phase1;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

public class ImageResize extends Plugin {
	/**
	 * Executes the request and returns PluginResult.
	 * 
	 * @param action
	 *            The action to execute.
	 * @param args
	 *            JSONArry of arguments for the plugin.
	 * @param callbackId
	 *            The callback id used when calling back into JavaScript.
	 * @return A PluginResult object with a status and message.
	 */
	public PluginResult execute(String action, JSONArray args, String callbackId) {
		boolean result;
		ArrayList<String> sourcePaths, failedPaths;
		String checkPath = "", targetPath = "";
		int tW = 0, tH = 0, ipl;
		JSONArray failedPathsJA;

		if (checkParamsNull(args) == true) {
			Log.e("BatchImageResize",
					"Error: null values not permitted as parameters");
			return new PluginResult(PluginResult.Status.ERROR);
		}
		try {
			try {
				tW = args.getInt(1);
				tH = args.getInt(2);
				if (tW < 0 || tH < 0) {
					Log.e("BatchImageResize",
							"Error: specify positive values for both height and width");
					return new PluginResult(PluginResult.Status.ERROR);
				}
			} catch (Exception e) {
				Log.e("BatchImageResize",
						"Error: height and width must be numeric");
				return new PluginResult(PluginResult.Status.ERROR);
			}

			ipl = args.getJSONArray(0).length();

			Log.e("BatchImageResize", "image paths array length = " + ipl);

			if (ipl == 0) {
				Log.e("BatchImageResize",
						"Error: image paths array cannot be of zero length");
				return new PluginResult(PluginResult.Status.ERROR);
			}

			sourcePaths = new ArrayList<String>();
			failedPaths = new ArrayList<String>();

			for (int i = 0; i < args.getJSONArray(0).length(); i++) {
				checkPath = args.getJSONArray(0).getString(i);
				if (isFileFound(checkPath) == true) {
					sourcePaths.add(checkPath);
					Log.e("BatchImageResize", "file exists: " + checkPath);
				} else
					Log.e("BatchImageResize", "file not found: " + checkPath);
			}

			ipl = sourcePaths.size();

			if (ipl == 0) {
				Log.e("BatchImageResize",
						"Error: image paths array must contain atleast one valid file path");
				return new PluginResult(PluginResult.Status.ERROR);
			}

			for (int i = 0; i < sourcePaths.size(); i++) {
				checkPath = sourcePaths.get(i);
				Log.e("BatchImageResize", "resizing image: " + checkPath);
				targetPath = checkPath;
				result = imageReSize(checkPath, tW, tH, targetPath);
				if (result == true)
					Log.e("BatchImageResize", "resized image: " + checkPath);
				else {
					Log.e("BatchImageResize", "unable to resize image: "
							+ checkPath);
					failedPaths.add(checkPath);
				}
			}

			failedPathsJA = new JSONArray();
			for (int i = 0; i < failedPaths.size(); i++)
				failedPathsJA.put(failedPaths.get(i));

			Log.e("BatchImageResize", "failed paths: " + "{\"Failed\":"
					+ failedPathsJA.toString() + "}");

			return new PluginResult(PluginResult.Status.OK,
					failedPathsJA.toString());
		} catch (JSONException e) {
			return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
		}
	}

	private boolean isFileFound(String path) {
		File file = new File(path);
		return file.exists();
	}

	private boolean checkParamsNull(JSONArray args) {
		for (int i = 0; i < args.length(); i++)
			if (args.isNull(i) == true)
				return true;

		return false;
	}

	private boolean imageReSize(String sourcePath, int targetWidth,
			int targetHeight, String targetPath) {
		File f;
		Bitmap b;
		Bitmap sb;
		String size = "0";

		int fh, fw, temp;

		try {
			b = BitmapFactory.decodeFile(sourcePath);
			Log.e("ImageResize",
					"Debug: Original Image[width,height]=[" + b.getWidth()
							+ "," + b.getHeight() + "]");

			// @note: we know that the current dimensions are already equal to
			// the target dimensions
			// so just exit, dont proceed further
			// this will prevent the image quality "degeneration" artifact
			// due to repeated execution of further code even if the image is
			// already of the target dimensions
			if ((b.getWidth() == targetWidth && b.getHeight() == targetHeight)
					|| (b.getHeight() == targetWidth && b.getWidth() == targetHeight)) {
				Log.e("ImageResize",
						"Debug: Original and Target image dimensions are already same, skipping");
				return true;
			}

			fw = b.getWidth();
			fh = b.getHeight();
			if (fh > fw)// portrait mode
			{
				Log.e("ImageResize",
						"Debug: Portrait mode image detected, swapping target width and height");
				temp = targetWidth;
				targetWidth = targetHeight;
				targetHeight = temp;
			} else// landscape
			{
				Log.e("ImageResize",
						"Debug: Landscape mode image detected, processing normally");
			}

			sb = Bitmap.createScaledBitmap(b, targetWidth, targetHeight, false);
			Log.e("ImageResize",
					"Debug: Resized Image[width,height]=[" + sb.getWidth()
							+ "," + sb.getHeight() + "]");

			OutputStream output = null;
			output = new BufferedOutputStream(new FileOutputStream(targetPath));
			Log.e("ImageResize", "Debug: Output file opened successfully");
			// @note: change the 100 below to control the output image quality
			// this will affect the output file size as well.
			sb.compress(Bitmap.CompressFormat.JPEG, 100, output);// @note:
																	// output
																	// format is
																	// jpeg
																	// only, ask
																	// peter
			Log.e("ImageResize", "Debug: Writing resized image to output file");
			output.close();
			Log.e("ImageResize", "Debug: Closing output file");
			return true;
		} catch (Exception e) {
			Log.e("ImageResize", "Exception: " + e.toString());
		}

		return false;
	}
}
